// fs/promises 提供异步方法
import fs from 'node:fs/promises';
import { clipFileName, extractNumbers, createRegExpFromArray, getUniquePairs } from '../common.js';

// 输出两个字符串的重叠部分，条件是至少含有一个数字，总字符数至少是1，并且至少有一个非数字
const getCommonSubstringsWithCondition = (str1, str2) => {
    const dp = Array.from({ length: str1.length + 1 }, () => Array(str2.length + 1).fill(0));
    const substrings = [];

    // 遍历动态规划表，收集所有符合条件的子串
    for (let i = 1; i <= str1.length; i++) {
        for (let j = 1; j <= str2.length; j++) {
            if (str1[i - 1] === str2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
                const length = dp[i][j];
                if (length >= 3) {
                    const start1 = i - length;
                    const end1 = i - 1;
                    const start2 = j - length;
                    const end2 = j - 1;
                    const substring = str1.substring(start1, end1 + 1);

                    // 新增条件：至少包含一个非数字字符、数字必须在非数字中间
                    if (substring.length >= 3 && /\d/.test(substring) && /\D/.test(substring) && /^\D+\d+\D+$/.test(substring)) {
                        substrings.push({
                            value: substring,
                            start1,
                            end1,
                            start2,
                            end2
                        });
                    }
                }
            }
        }
    }

    // 去重：防止重复的子串
    const seen = new Set();
    const uniqueSubstrings = [];
    for (const sub of substrings) {
        const key = `${sub.value}-${sub.start1}-${sub.end1}-${sub.start2}-${sub.end2}`;
        if (!seen.has(key)) {
            seen.add(key);
            uniqueSubstrings.push(sub);
        }
    }

    // 按子串长度降序排序，确保优先选择更长的
    uniqueSubstrings.sort((a, b) => b.value.length - a.value.length);

    // 贪心算法：选择不重叠的子串（在两个字符串中均不重叠）
    const result = [];
    let lastEnd1 = -1;
    let lastEnd2 = -1;
    for (const sub of uniqueSubstrings) {
        if (sub.start1 > lastEnd1 && sub.start2 > lastEnd2) {
            result.push(sub.value);
            lastEnd1 = sub.end1;
            lastEnd2 = sub.end2;
        }
    }

    return result;
};

const normalizeStringByCommonSubstring = (arr, startAttrName, EndAttrName) => {
    const towAllArrays = getUniquePairs(arr);
    const sameSArr = new Set();
    towAllArrays.forEach(([s, e]) => {
        getCommonSubstringsWithCondition(s[startAttrName], e[startAttrName]).forEach(str => sameSArr.add(str));
    });
    const exp = createRegExpFromArray(sameSArr.values());
    // console.log('看看exp', exp);
    arr.forEach(item => {
        item[EndAttrName] = item.newName.replace(exp, '-');
    });

    return arr;
};

// 输入{ 'a':'1' }
const findMultipleContinuousSequences = obj => {
    const keys = Object.keys(obj);
    const arrays = keys.map(key => ({
        key,
        array: obj[key].numArr
            .map(num => {
                // 统一转成数字，并过滤非有效数字
                const parsed = parseInt(num, 10);
                return isNaN(parsed) ? null : parsed;
            })
            .filter(num => num !== null && num > 0),
        newName: obj[key].newName,
        fileName: obj[key].fileName,
        typeStr: obj[key].typeStr,
        newCompName: '' // 计算名称，暂时为空
    }));

    // 计算强度为2次足矣,从newName到newCompName，第二次从newCompName到newCompName2
    normalizeStringByCommonSubstring(arrays, 'newName', 'newCompName');
    normalizeStringByCommonSubstring(arrays, 'newCompName', 'newCompName2');

    

    arrays.forEach(item => {
        item.array = extractNumbers(item.newCompName2).map(num => parseInt(num, 10))
    });

   console.log('看看arrays', arrays);

/*       
    key: '[Dont be a simp] Ore dake Level Up na Ken Season 2 - 02 [WebRip 2160p HEVC-10bit AAC Multi-Subs].mkv',
    array: [ 2, 2, 2160, 10 ],
    newName: '[Dont be a simp] Ore dake Level Up na Ken Season 2 - 02 [WebRip 2160p HEVC-10bit AAC Multi-Subs]',
    fileName: '[Dont be a simp] Ore dake Level Up na Ken Season 2 - 02 [WebRip 2160p HEVC-10bit AAC Multi-Subs].mkv',
    typeStr: 'mkv',
    newCompName: '-02-10bit AAC Multi-Subs]' */

    /*     arrays [
  {
    key: '11 [WebRip 2160p HEVC-10bit AAC Multi-Subs].mkv',
    array: [ 11, 2160, 10 ]
  },
  {
    key: 'evel Up na Ken Season 2 - 04 [WebRip 2160p HEVC-10bit AAC Multi-Subs].mkv',
    array: [ 2, 4, 2160, 10 ]
  }, */
    /*   keys [
  '11 [WebRip 2160p HEVC-10bit AAC Multi-Subs].mkv',
  'evel Up na Ken Season 2 - 04 [WebRip 2160p HEVC-10bit AAC Multi-Subs].mkv', */

    // 收集所有正数
    const allNums = arrays.flatMap(item => item.array);

    if (allNums.length === 0) return false;

    // 去重排序后尝试作为起始点
    const uniqueNums = [...new Set(allNums)].sort((a, b) => a - b);
    const validMaps = [];

    for (let i = 0; i < uniqueNums.length; i++) {
        const start = uniqueNums[i];
        const length = keys.length;
        const expectedSequence = Array.from({ length }, (_, idx) => start + idx);

        const resultMap = [];

        for (let j = 0; j < expectedSequence.length; j++) {
            const num = expectedSequence[j];

            for (let k = 0; k < arrays.length; k++) {
                // 以num为主
                if (arrays[k].array.includes(num)) {
                    const index = resultMap.findIndex(item => item.num === num);
                    if (index === -1) {
                        resultMap.push({
                            num,
                            objArr: [arrays[k]]
                        });
                    } else {
                        resultMap[index].objArr.push(arrays[k]);
                    }
                }
            }

            if (Object.keys(resultMap).length === length) {
                validMaps.push(resultMap);
            }
        }
    }

    for (let v = 0; v < validMaps.length; v++) {
        const rm = validMaps[v];
        const oneA = rm.filter(item => item.objArr.length === 1);
        const oneAKeys = oneA.map(item => item.objArr[0].key);
        const towMoreA = rm.filter(item => item.objArr.length > 1);
        towMoreA.forEach(item => {
            const objArr = item.objArr;
            oneAKeys.forEach(key => {
                const index = objArr.findIndex(itemx => itemx.key === key);
                if (index > -1) {
                    objArr.splice(index, 1);
                }
            });
            item.objArr = objArr;
        });
    }

    // 输出逻辑
    if (validMaps.length >= 2) {
        return true;
    } else if (validMaps.length === 1) {
        return validMaps[0];
    } else {
        return false;
    }
};

// 输入路径
const inputDir = String.raw`E:\迅雷下载\我独自升级第二季 - 副本`;

// 默认为1,就是保留文件末尾多少个“."，最小值是0,如果是0,则把文件格式一起给改没了，所以请慎重。非必要不碰
const typeNum = 1;
/**
 * 获取指定目录下的所有非隐藏、非文件夹的文件名列表
 * @param {string} dirPath - 要读取的文件夹路径
 * @returns {Promise<string[]>} - 文件名数组
 */
const getNonHiddenFiles = async dirPath =>
    await fs
        .readdir(dirPath, { withFileTypes: true })
        .then(
            files =>
                files
                    .filter(file => !file.isDirectory()) // 排除文件夹
                    .filter(file => !file.name.startsWith('.')) // 排除隐藏文件
                    .map(file => file.name) // 只保留文件名
        )
        .catch(error => {
            console.error('读取文件夹出错:', error.message);
            throw error;
        });

getNonHiddenFiles(inputDir)
    .then(files => {
        const fileNames = files.map(fileName => {
            const { newName, typeStr } = clipFileName(fileName, typeNum);
            const numArr = extractNumbers(newName);
            return { fileName, newName, typeStr, numArr };
        });
        const obj = fileNames.reduce((acc, { fileName, newName, typeStr, numArr }) => {
            acc[fileName] = {
                numArr: numArr.map(num => parseInt(num, 10)),
                newName,
                fileName,
                typeStr
            };
            return acc;
        }, {});
        // console.log('文件:', obj);
        console.log(JSON.stringify(findMultipleContinuousSequences(obj)));
    })
    .catch(err => console.error('错误:', err));
